home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / comm / wnos5src.zip / IFACE.C < prev    next >
Text File  |  1993-08-09  |  11KB  |  523 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "config.h"
  4. #include "mbuf.h"
  5. #include "proc.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "netuser.h"
  9. #include "ax25.h"
  10. #include "enet.h"
  11. #include "pktdrvr.h"
  12. #include "cmdparse.h"
  13. #include "commands.h"
  14.  
  15. /* Loopback pseudo-interface */
  16. struct iface Loopback = {
  17.     &Encap,            /* Link to next entry */
  18.     "loopback",        /* name        */
  19.     CL_NONE,        /* type        */
  20.     &Iftypes[0],    /* iftype    */
  21.     0x7f000001L,    /* addr        127.0.0.1 */
  22.     0xffffffffL,    /* broadcast    255.255.255.255 */
  23.     0xffffffffL,    /* netmask    255.255.255.255 */
  24.     NULL,            /* (*ioctl)    */
  25.     NULLFP,            /* (*send)    */
  26.     NULLFP,            /* (*output)    */
  27.     NULLFP,            /* (*raw)    */
  28.     NULLFP,            /* (*stop)    */
  29.     NULLFP,            /* (*status)    */
  30.     MAXINT16,        /* mtu        No limit */
  31.     0,                /* dev        */
  32.     0,                /* xdev        */
  33.     0,                /* port     */
  34.     0,                /* trace    */
  35.     NULLCHAR,        /* trfile    */
  36.     NULLFILE,        /* trfp        */
  37.     NULLCHAR,        /* hwaddr    */
  38.     NULLIF,            /* forw        */
  39.     0,                /* ipsndcnt    */
  40.     0,                /* rawsndcnt    */
  41.     0,                /* iprcvcnt    */
  42.     0,                /* rawrcvcnt    */
  43.     0,                /* lastsent    */
  44.     0,                /* lastrecv    */
  45.     NULLPROC,        /* rxproc    */
  46.     NULLPROC,        /* txproc    */
  47.     NULLPROC,        /* supv        */
  48.     NULL,            /* extension    */
  49.     0,
  50.     NULLLQ,
  51.     MAXDEFAULT,
  52.     0,
  53. };
  54.  
  55. /* Encapsulation pseudo-interface */
  56. struct iface Encap = {
  57.     NULLIF,
  58.     "encap",        /* name        */
  59.     CL_NONE,        /* type        */
  60.     &Iftypes[0],    /* iftype    */
  61.     INADDR_ANY,        /* addr        0.0.0.0 */
  62.     0xffffffffL,    /* broadcast    255.255.255.255 */
  63.     0xffffffffL,    /* netmask    255.255.255.255 */
  64.     NULL,            /* (*ioctl)    */
  65.     ip_encap,        /* (*send)    */
  66.     NULLFP,            /* (*output)    */
  67.     NULLFP,            /* (*raw)    */
  68.     NULLFP,            /* (*stop)    */
  69.     NULLFP,            /* (*status)    */
  70.     MAXINT16,        /* mtu        No limit */
  71.     0,                /* dev        */
  72.     0,                /* xdev        */
  73.     0,                /* port        */
  74.     0,                /* trace    */
  75.     NULLCHAR,        /* trfile    */
  76.     NULLFILE,        /* trfp        */
  77.     NULLCHAR,        /* hwaddr    */
  78.     NULLIF,            /* forw        */
  79.     0,                /* ipsndcnt    */
  80.     0,                /* rawsndcnt    */
  81.     0,                /* iprcvcnt    */
  82.     0,                /* rawrcvcnt    */
  83.     0,                /* lastsent    */
  84.     0,                /* lastrecv    */
  85.     NULLPROC,        /* rxproc    */
  86.     NULLPROC,        /* txproc    */
  87.     NULLPROC,        /* supv        */
  88.     NULL,            /* extension    */
  89.     0,
  90.     NULLLQ,
  91.     MAXDEFAULT,
  92.     0,
  93. };
  94.  
  95. /* Interface list header */
  96. struct iface *Ifaces = &Loopback;
  97.  
  98. char Badif[] = "Interface %s unknown\n";
  99. char Badax[] = "Interface %s not AX25\n";
  100. char Badasy[] = "Interface %s not ASY port\n";
  101. char Noipaddr[] = "IP adress not set\n";
  102. char Ifexist[] = "Interface %s already exists\n";
  103.  
  104. #ifdef AX25
  105. void
  106. init_flags(struct iface *ifp)
  107. {
  108.     ifp->flags = mxallocw(sizeof(struct flags));
  109.  
  110.     ifp->flags->maxframe = Maxframe;
  111.     ifp->flags->t1init   = T1init;
  112.     ifp->flags->t2init   = T2init;
  113.     ifp->flags->t3init   = T3init;
  114.     ifp->flags->t4init   = T4init;
  115.     ifp->flags->t5init   = T5init;
  116.     ifp->flags->retries  = Retries;
  117.     ifp->flags->axwindow = Axwindow;
  118.     ifp->flags->paclen   = Paclen;
  119.     ifp->flags->pthresh  = Pthresh;
  120.     ifp->flags->digipeat = Digipeat;
  121.     ifp->flags->t3disc   = T3disc;
  122. }
  123. #endif
  124.  
  125. /* Given a network mask, return the number of contiguous 1-bits starting
  126.  * from the most significant bit.
  127.  */
  128. static int near
  129. mask2width(int32 mask)
  130. {
  131.     int i, width = 0;
  132.  
  133.     for(i = 31; i >= 0; i--) {
  134.         if(!(mask & (1 << i))) {
  135.             break;
  136.         }
  137.         width++;
  138.     }
  139.     return width;
  140. }
  141.  
  142. /* Set interface IP address */
  143. static int
  144. ifipaddr(int argc,char **argv,void *p)
  145. {
  146.     struct iface *ifp = p;
  147.     int32 addr;
  148.  
  149.     if((addr = resolve(argv[1])) == 0) {
  150.         tprintf(Badhost,argv[1]);
  151.         return -1;
  152.     }
  153.     ifp->addr = addr;
  154.     return 0;
  155. }
  156.  
  157. /* Set link (hardware) address */
  158. static int
  159. iflinkadr(int argc,char **argv,void *p)
  160. {
  161.     struct iface *ifp = p;
  162.  
  163.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL) {
  164.         tputs("Can't set link address\n");
  165.         return -1;
  166.     }
  167.     if(*ifp->iftype->scan != 0) {
  168.         if(ifp->hwaddr != NULLCHAR) {
  169.             xfree(ifp->hwaddr);
  170.         }
  171.         ifp->hwaddr = mxallocw(ifp->iftype->hwalen);
  172.         return (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  173.     }
  174.     return 0;
  175. }
  176.  
  177. /* Set interface broadcast address. This is actually done
  178.  * by installing a private entry in the routing table.
  179.  */
  180. static int
  181. ifbroad(int argc,char **argv,void *p)
  182. {
  183.     struct iface *ifp = p;
  184.     struct route *rp;
  185.  
  186.     if((rp = rt_blookup(ifp->broadcast,32)) != NULLROUTE && rp->iface == ifp) {
  187.         rt_drop(ifp->broadcast,32);
  188.     }
  189.     if((ifp->broadcast = resolve(argv[1])) == 0) {
  190.         tprintf(Badhost,argv[1]);
  191.         return -1;
  192.     }
  193.     rt_add(ifp->broadcast,32,0,ifp,1,0,1);
  194.     return 0;
  195. }
  196.  
  197. static int
  198. ifname(int argc,char **argv,void *p)
  199. {
  200.     struct iface *ifp = p;
  201.  
  202.     if(ifp->name != NULLCHAR) {
  203.         xfree(ifp->name);
  204.     }
  205.     ifp->name = strxdup(argv[1]);
  206.     return 0;
  207. }
  208.  
  209. /* Set the network mask. This is actually done by installing
  210.  * a routing entry.
  211.  */
  212. static int
  213. ifnetmsk(int argc,char **argv,void *p)
  214. {
  215.     struct iface *ifp = p;
  216.     struct route *rp;
  217.  
  218.     /* Remove old entry if it exists */
  219.     if((rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask))) != NULLROUTE) {
  220.         rt_drop(rp->target,rp->bits);
  221.     }
  222.     ifp->netmask = htol(argv[1]);
  223.     rt_add(ifp->addr,mask2width(ifp->netmask),0,ifp,0,0,0);
  224.     return 0;
  225. }
  226.  
  227. /* Command to set interface encapsulation mode */
  228. static int
  229. ifencap(int argc,char **argv,void *p)
  230. {
  231.     struct iface *ifp = p;
  232.  
  233.     if(setencap(ifp,argv[1]) != 0) {
  234.         tprintf("Encap mode %s unknown\n",argv[1]);
  235.         return 1;
  236.     }
  237.     return 0;
  238. }
  239.  
  240. /* Function to set encapsulation mode */
  241. int
  242. setencap(struct iface *ifp,char *mode)
  243. {
  244.     struct iftype *ift;
  245.  
  246.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++) {
  247.         if(strnicmp(ift->name,mode,strlen(mode)) == 0) {
  248.             break;
  249.         }
  250.     }
  251.     if(ift->name == NULLCHAR) {
  252.         return -1;
  253.     }
  254.     ifp->iftype = ift;
  255.     ifp->send = ift->send;
  256.     ifp->output = ift->output;
  257.     ifp->type = ift->type;
  258.     return 0;
  259. }
  260.  
  261. #ifdef XXX
  262. /* Set interface receive buffer size */
  263. static int
  264. ifrxbuf(int argc,char **argv,void *p)
  265. {
  266.     return 0;    /* To be written */
  267. }
  268. #endif
  269.  
  270. /* Set interface Maximum Transmission Unit */
  271. static int
  272. ifmtu(int argc,char **argv,void *p)
  273. {
  274.     struct iface *ifp = p;
  275.  
  276.     ifp->mtu = atoi(argv[1]);
  277.     return 0;
  278. }
  279.  
  280. /* Set interface forwarding */
  281. static int
  282. ifforw(int argc,char **argv,void *p)
  283. {
  284.     struct iface *ifp = p;
  285.  
  286.     if((ifp->forw = if_lookup(argv[1])) == NULLIF) {
  287.         return -1;
  288.     }
  289.     if(ifp->forw == ifp) {
  290.         ifp->forw = NULLIF;
  291.     }
  292.     return 0;
  293. }
  294.  
  295. /* Display the parameters for a specified interface */
  296. static void near
  297. showiface(struct iface *ifp)
  298. {
  299.     char tmp[25];
  300.  
  301.     tprintf("%-10s IP addr %s MTU %u Link encap ",
  302.         ifp->name,inet_ntoa(ifp->addr),ifp->mtu);
  303.     if(ifp->iftype == NULLIFT) {
  304.         tputs("not set\n");
  305.     } else {
  306.         tprintf("%s\n",ifp->iftype->name);
  307.  
  308.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
  309.             tprintf("%20s %s\n",
  310.               "Link addr",(*ifp->iftype->format)(tmp,ifp->hwaddr));
  311.         }
  312.     }
  313.     tprintf("%16s 0x%x netmask 0x%08lx\n",
  314.         "trace",ifp->trace,ifp->netmask);
  315.     tprintf("%19s %lu tot %lu idle %s\n",
  316.         "sent: ip",ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  317.     tprintf("%19s %lu tot %lu idle %s\n",
  318.         "recv: ip",ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  319.     if(ifp->forw != NULLIF) {
  320.         tprintf("%28s %s\n","output forward to",ifp->forw->name);
  321.     }
  322. }
  323.  
  324. /* Command to detach an interface */
  325. int
  326. dodetach(int argc,char **argv,void *p)
  327. {
  328.     struct iface *ifp;
  329.  
  330.     if((ifp = if_lookup(argv[1])) == NULLIF){
  331.         tprintf(Badif,argv[1]);
  332.         return 1;
  333.     }
  334.     if(if_detach(ifp) == -1) {
  335.         tputs("Can't detach loopback interface\n");
  336.     }
  337.     return 0;
  338. }
  339.  
  340. /* Detach a specified interface */
  341. int
  342. if_detach(struct iface *ifp)
  343. {
  344.     struct iface *iftmp;
  345.     struct route *rp, *rptmp = NULLROUTE;
  346.  
  347.     if(ifp == &Loopback || ifp == &Encap) {
  348.         return -1;
  349.     }
  350.     /* Drop all routes that point to this interface */
  351.     if(R_default.iface == ifp) {
  352.         rt_drop(0,0);    /* Drop default route */
  353.     }
  354.     for(rp = Routes; rp != NULLROUTE; rp = rptmp) {
  355.         rptmp = rp->next;
  356.         if(rp->iface == ifp) {
  357.             rt_drop(rp->target,rp->bits);
  358.         }
  359.     }
  360.     /* Unforward any other interfaces forwarding to this one */
  361.     for(iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
  362.         if(iftmp->forw == ifp) {
  363.             iftmp->forw = NULLIF;
  364.         }
  365.     }
  366.     /* Call device shutdown routine, if any */
  367.     if(ifp->stop != NULLFP) {
  368.         (*ifp->stop)(ifp,0);
  369.     }
  370.     killproc(ifp->proc);
  371.     killproc(ifp->proc1);
  372.     killproc(ifp->supv);
  373.  
  374.     /* Free allocated memory associated with this interface */
  375.     if(ifp->name != NULLCHAR) {
  376.         xfree(ifp->name);
  377.     }
  378.     if(ifp->hwaddr != NULLCHAR) {
  379.         xfree(ifp->hwaddr);
  380.     }
  381.     /* Remove from interface list */
  382.     if(ifp == Ifaces) {
  383.         Ifaces = ifp->next;
  384.     } else {
  385.         /* Search for entry just before this one
  386.          * (necessary because list is only singly-linked.)
  387.          */
  388.         for(iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
  389.             if(iftmp->next == ifp) {
  390.                 break;
  391.             }
  392.         }
  393.         if(iftmp != NULLIF && iftmp->next == ifp) {
  394.             iftmp->next = ifp->next;
  395.         }
  396.     }
  397.     if(ifp->lq != NULLLQ) {
  398.         xfree(ifp->lq);
  399.     }
  400.     /* Finally free the structure itself */
  401.     xfree(ifp);
  402.     return 0;
  403. }
  404.  
  405. /* Given the ascii name of an interface, return a pointer to the structure,
  406.  * or NULLIF if it doesn't exist
  407.  */
  408. struct iface *
  409. if_lookup(char *name)
  410. {
  411.     struct iface *ifp;
  412.  
  413.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  414.         if(strcmp(ifp->name,name) == 0) {
  415.             return ifp;
  416.         }
  417.     }
  418.     return NULLIF;
  419. }
  420.  
  421. struct iface *
  422. cmp_if(char *ifname)
  423. {
  424.     struct iface *ifp;
  425.  
  426.     if((ifp = if_lookup(ifname)) == NULLIF) {
  427.         tprintf(Badif,ifname);
  428.         return NULLIF;
  429.     }
  430.     if(ifp->output != ax_output) {
  431.         tprintf(Badax,ifname);
  432.         return NULLIF;
  433.     }
  434.     return ifp;
  435. }
  436.  
  437. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  438.  * NULLIF otherwise.
  439.  * This is used to tell if an incoming IP datagram is for us, or if it
  440.  * has to be routed.
  441.  */
  442. struct iface *
  443. ismyaddr(int32 addr)
  444. {
  445.     struct iface *ifp;
  446.  
  447.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
  448.         if(addr == ifp->addr) {
  449.             return ifp;
  450.         }
  451.     }
  452.     return NULLIF;
  453. }
  454.  
  455. /* return buffer with name + comment */
  456. char *
  457. if_name(struct iface *ifp,char *comment)
  458. {
  459.     char *result = mxallocw(strlen(ifp->name) + strlen(comment) + 2);
  460.     sprintf(result,"%s%s",ifp->name,comment);
  461.     return result;
  462. }
  463.  
  464. #ifdef ASY
  465. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  466. int
  467. bitbucket(struct iface *ifp,struct mbuf *bp)
  468. {
  469.     free_p(bp);
  470.     return 0;
  471. }
  472. #endif
  473.  
  474. /* Set interface parameters */
  475. int
  476. doifconfig(int argc,char **argv,void *p)
  477. {
  478.     struct iface *ifp;
  479.     int i;
  480.  
  481.     struct cmds Ifcmds[] = {
  482.         "broadcast",        ifbroad,    0,    2,    NULLCHAR,
  483.         "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  484.         "forward",            ifforw,        0,    2,    NULLCHAR,
  485.         "ipaddress",        ifipaddr,    0,    2,    NULLCHAR,
  486.         "linkaddress",        iflinkadr,    0,    2,    NULLCHAR,
  487.         "mtu",                ifmtu,        0,    2,    NULLCHAR,
  488.         "name",                ifname,        0,  2,  NULLCHAR,
  489.         "netmask",            ifnetmsk,    0,    2,    NULLCHAR,
  490. #ifdef XXX
  491.         "rxbuf",            ifrxbuf,    0,    2,    NULLCHAR,
  492. #endif
  493.         NULLCHAR,
  494.     };
  495.  
  496.     if(argc < 2) {
  497.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next) {
  498.             showiface(ifp);
  499.         }
  500.         return 0;
  501.     }
  502.     if((ifp = if_lookup(argv[1])) == NULLIF) {
  503.         tprintf(Badif,argv[1]);
  504.         return -1;
  505.     }
  506.     if(argc == 2) {
  507.         showiface(ifp);
  508.         if(ifp->status != NULLFP) {
  509.             (*ifp->status)(ifp);
  510.         }
  511.         return 0;
  512.     }
  513.     if(argc == 3) {
  514.         tputs("Argument missing\n");
  515.         return -1;
  516.     }
  517.     for(i = 2; i < argc - 1; i += 2) {
  518.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  519.     }
  520.     return 0;
  521. }
  522.  
  523.